/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __PONY_HAL_GPIO_H__
#define __PONY_HAL_GPIO_H__

/* includes (standard library, system) ---------------------------------------*/
#include <stdint.h>
#include <stddef.h>
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <x_symbol.h>
/* includes (local) ----------------------------------------------------------*/
#include "hal_it.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* defines -------------------------------------------------------------------*/
/* typedefs ------------------------------------------------------------------*/

enum hal_gpio_mode {
    HAL_GPIO_MODE_INPUT,     /*!< Input Floating Mode                   */
    HAL_GPIO_MODE_OUTPUT_PP, /*!< Output Push Pull Mode                 */
    HAL_GPIO_MODE_OUTPUT = HAL_GPIO_MODE_OUTPUT_PP,
    HAL_GPIO_MODE_OUTPUT_OD, /*!< Output Open Drain Mode                */
    HAL_GPIO_MODE_AF_PP,     /*!< Alternate Function Push Pull Mode     */
    HAL_GPIO_MODE_AF_OD,     /*!< Alternate Function Open Drain Mode    */
    HAL_GPIO_MODE_AF_INPUT,
    HAL_GPIO_MODE_ANALOG,     /*!< Analog Mode  */
    HAL_GPIO_MODE_IT_RISING,  /*!< External Interrupt Mode with Rising edge trigger detection  */
    HAL_GPIO_MODE_IT_FALLING, /*!< External Interrupt Mode with Falling edge trigger detection */
    HAL_GPIO_MODE_IT_RISING_FALLING /*!< External Interrupt Mode with Rising/Falling edge trigger
                                       detection  */
};

enum hal_gpio_pull {
    HAL_GPIO_NOPULL,  /*!< No Pull-up or Pull-down activation (default) */
    HAL_GPIO_PULLUP,  /*!< Pull-up activation                  */
    HAL_GPIO_PULLDOWN /*!< Pull-down activation                */
};

enum hal_gpio_speed {
    HAL_GPIO_SPEED_FREQ_HIGH, /* default */
    HAL_GPIO_SPEED_FREQ_VERY_HIGH,
    HAL_GPIO_SPEED_FREQ_MEDIUM,
    HAL_GPIO_SPEED_FREQ_LOW
};

typedef struct hal_gpio {
    uint8_t gpio; /* 0-GPIOA, 1-GPIOB, ... */
    uint8_t pin;  /* pin number 0, 1, 2 ... */
    uint8_t mode;
    uint8_t pull : 2;
    uint8_t speed : 3;
    uint8_t reserved1 : 3;
    uint16_t prio; /* interrupt priority */
    uint16_t reserved2;
    hal_it_handler_t handler;
    uintptr_t arg;  /* handler arg */
    uintptr_t priv; /* private data */
} hal_gpio_t;

/* macro ---------------------------------------------------------------------*/

#define HAL_GPIO_IS_IT_MODE(mode)                                                                  \
    (((mode) == HAL_GPIO_MODE_IT_RISING) || ((mode) == HAL_GPIO_MODE_IT_FALLING) ||                \
     ((mode) == HAL_GPIO_MODE_IT_RISING_FALLING))

/* inlines -------------------------------------------------------------------*/
/* externs -------------------------------------------------------------------*/

extern int hal_gpio_init(hal_gpio_t *gpio);
extern int hal_gpio_write(hal_gpio_t *gpio, uint8_t data);
extern int hal_gpio_read(hal_gpio_t *gpio, uint8_t *data);
extern int hal_gpio_toggle(hal_gpio_t *gpio);
extern int hal_gpio_irq(hal_gpio_t *gpio, uint8_t enable);
extern void hal_gpio_it_handler(hal_gpio_t *gpio);
extern uint8_t hal_gpio_state(hal_gpio_t *gpio);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __PONY_HAL_GPIO_H__ */
